﻿using System.Collections.Generic;
using UnityEngine;
using Unity.Mathematics;

namespace Jinndev {

    public static class MeshUtil {

        public static MeshRenderer AddMeshRenderer(GameObject gameObject, Material material) {
            MeshRenderer meshRenderer = gameObject.AddComponent<MeshRenderer>();
            meshRenderer.material = material;
            meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
            meshRenderer.receiveShadows = false;
            return meshRenderer;
        }

        public static MeshFilter AddMeshFilter(GameObject gameObject, Mesh mesh) {
            MeshFilter meshFilter = gameObject.AddComponent<MeshFilter>();
            meshFilter.mesh = mesh;
            return meshFilter;
        }

        // horizontal 左：-1, 右：1 
        public static Mesh CreateCornerMesh(float length, int horizontal) {
            int n = 20; // 弧线分成n段
            float angle = 90f / n;
            //float magnitude = new Vector2(length, length).magnitude;

            Mesh mesh = new Mesh();

            List<Vector3> vertices = new List<Vector3>();
            List<int> triangles = new List<int>();
            List<Vector2> uv = new List<Vector2>();

            float half = 0.5f * length;
            Vector3 zero = new Vector3(half * horizontal, -half, 0);
            //Vector3 zero = new Vector3(horizontal, -horizontal, 0);

            for (int i = 0; i <= n; i++) {
                vertices.Add(zero);
                uv.Add(Vector2.Lerp(new Vector2(1 * horizontal, 0), new Vector2(1 * horizontal, 1), (float)i / n));

                float x = length * Mathf.Cos(angle * i * Mathf.Deg2Rad);
                float y = length * Mathf.Sin(angle * i * Mathf.Deg2Rad);
                vertices.Add(zero + new Vector3(-x * horizontal, y, 0));
                uv.Add(Vector2.Lerp(new Vector2(0, 0), new Vector2(0, 1), (float)i / n));
            }

            //0        1        2        3
            //0 1 3    2 3 5    4 5 7    6 7 9
            if (horizontal > 0) {
                for (int i = 0; i < n; i++) {
                    triangles.Add(i * 2 + 0);
                    triangles.Add(i * 2 + 1);
                    triangles.Add(i * 2 + 3);
                }
            }
            else {
                for (int i = 0; i < n; i++) {
                    triangles.Add(i * 2 + 3);
                    triangles.Add(i * 2 + 1);
                    triangles.Add(i * 2 + 0);
                }
            }

            mesh.vertices = vertices.ToArray();
            mesh.triangles = triangles.ToArray();
            mesh.uv = uv.ToArray();

            mesh.RecalculateNormals();
            mesh.RecalculateTangents();
            mesh.RecalculateBounds();
            return mesh;
        }

        /// <summary>
        /// 矩形mesh
        /// </summary>
        public static Mesh CreateRectMesh(float2 size, float2 pivot) {
            /// 2 3
            /// 0 1
            float minX = -pivot.x * size.x;
            float maxX = (1 - pivot.x) * size.x;
            float minY = -pivot.y * size.y;
            float maxY = (1 - pivot.y) * size.y;

            Mesh mesh = new Mesh();
            mesh.vertices = new Vector3[] {
                new Vector3(minX, minY, 0),
                new Vector3(maxX, minY, 0),
                new Vector3(minX, maxY, 0),
                new Vector3(maxX, maxY, 0),
            };
            mesh.triangles = new int[] {
                0, 2, 3,
                0, 3, 1,
            };
            mesh.uv = new Vector2[] {
                new Vector2(0, 0),
                new Vector2(1, 0),
                new Vector2(0, 1),
                new Vector2(1, 1),
            };
            mesh.RecalculateNormals();
            mesh.RecalculateTangents();
            mesh.RecalculateBounds();
            return mesh;
        }

        /// <summary>
        /// 九宫格mesh
        /// </summary>
        /// <param name="size">mesh大小(WorldSpace)</param>
        /// <param name="pivot">你懂的</param>
        /// <param name="padding">mesh边框大小(WorldSpace)，即四周边框的大小值</param>
        /// <param name="uvBorder">uv边框大小(UVSpace)，即四周边框占图形的比例</param>
        /// <returns></returns>
        public static Mesh CreateSlicedMesh(float2 size, float2 pivot, Padding padding, Padding uvBorder) {
            /// 12 13 14 15
            /// 8  9  10 11
            /// 4  5  6  7
            /// 0  1  2  3
            float minX = -pivot.x * size.x;
            float maxX = (1 - pivot.x) * size.x;
            float minY = -pivot.y * size.y;
            float maxY = (1 - pivot.y) * size.y;

            Mesh mesh = new Mesh();

            mesh.vertices = new Vector3[] {
                new Vector3(minX,                 minY, 0),
                new Vector3(minX + padding.left,  minY, 0),
                new Vector3(maxX - padding.right, minY, 0),
                new Vector3(maxX,                 minY, 0),

                new Vector3(minX,                 minY + padding.bottom, 0),
                new Vector3(minX + padding.left,  minY + padding.bottom, 0),
                new Vector3(maxX - padding.right, minY + padding.bottom, 0),
                new Vector3(maxX,                 minY + padding.bottom, 0),

                new Vector3(minX,                 maxY - padding.top, 0),
                new Vector3(minX + padding.left,  maxY - padding.top, 0),
                new Vector3(maxX - padding.right, maxY - padding.top, 0),
                new Vector3(maxX,                 maxY - padding.top, 0),

                new Vector3(minX,                 maxY, 0),
                new Vector3(minX + padding.left,  maxY, 0),
                new Vector3(maxX - padding.right, maxY, 0),
                new Vector3(maxX,                 maxY, 0),
            };

            List<int> triangles = new List<int>();
            for (int y = 0; y < 3; y++) {
                for (int x = 0; x < 3; x++) {
                    int t = y * 4 + x;
                    triangles.AddRange(new int[] { t, t + 4, t + 5 });
                    triangles.AddRange(new int[] { t, t + 5, t + 1 });
                }
            }
            mesh.triangles = triangles.ToArray();

            mesh.uv = new Vector2[] {
                new Vector2(0,                  0),
                new Vector2(0 + uvBorder.left,  0),
                new Vector2(1 - uvBorder.right, 0),
                new Vector2(1,                  0),

                new Vector2(0,                  0 + uvBorder.bottom),
                new Vector2(0 + uvBorder.left,  0 + uvBorder.bottom),
                new Vector2(1 - uvBorder.right, 0 + uvBorder.bottom),
                new Vector2(1,                  0 + uvBorder.bottom),

                new Vector2(0,                  1 - uvBorder.top),
                new Vector2(0 + uvBorder.left,  1 - uvBorder.top),
                new Vector2(1 - uvBorder.right, 1 - uvBorder.top),
                new Vector2(1,                  1 - uvBorder.top),

                new Vector2(0,                  1),
                new Vector2(0 + uvBorder.left,  1),
                new Vector2(1 - uvBorder.right, 1),
                new Vector2(1,                  1),
            };

            mesh.RecalculateNormals();
            mesh.RecalculateTangents();
            mesh.RecalculateBounds();
            return mesh;
        }

        /// <summary>
        /// 根据sprite创建9宫格mesh
        /// </summary>
        /// <param name="size"></param>
        /// <param name="pivot"></param>
        /// <param name="sprite"></param>
        /// <returns></returns>
        public static Mesh CreateSlicedMesh(float2 size, float2 pivot, Sprite sprite) {
            if(sprite == null) {
                return null;
            }
            float top = sprite.border.w / sprite.rect.size.y;
            float right = sprite.border.z / sprite.rect.size.x;
            float bottom = sprite.border.y / sprite.rect.size.y;
            float left = sprite.border.x / sprite.rect.size.x;

            //float2 scale = size / 1f;
            //Padding padding = new Padding(top * scale.x, right * scale.x, bottom * scale.y, left * scale.y);
            Padding uvPadding = new Padding(top, right, bottom, left);

            return CreateSlicedMesh(size, pivot, uvPadding, uvPadding);
        }

    }

}
